<template>
  <router-view v-slot="{ Component }">
    <transition
      :name="transitionName"
      @before-enter="onEnter"
      @before-leave="onLeave"
    >
      <keep-alive :include="isKeepAlive">
        <component
          :class="{ 'fixed top-0 left-0 w-screen z-50': isAnimation }"
          :is="Component"
        />
      </keep-alive>
    </transition>
  </router-view>
</template>
<script>
const NONE = 'none'
const ROUTER_VIEW_PUSH = 'push'
const ROUTER_VIEW_BACK = 'back'
</script>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const props = defineProps({
  routerType: {
    type: String,
    default: NONE,
    validate(val) {
      const result = [ROUTER_VIEW_PUSH, ROUTER_VIEW_BACK].includes(val)
      if (!result) {
        throw new Error(
          `routerType must be one of ${[ROUTER_VIEW_PUSH, ROUTER_VIEW_BACK]}`
        )
      }
      return result
    }
  },
  mainComponentName: {
    type: String,
    required: true
  }
})
const transitionName = ref('')
// 记录需要被缓存的组件
const isKeepAlive = ref([props.mainComponentName])
router.beforeEach((to) => {
  transitionName.value = props.routerType
  if (props.routerType === ROUTER_VIEW_PUSH) {
    isKeepAlive.value.push(to.name)
  }
  if (props.routerType === ROUTER_VIEW_BACK) {
    isKeepAlive.value.pop()
  }
  if (to.name === props.mainComponentName) {
    clearKeepAlive()
  }
})
// 清空
const clearKeepAlive = () => {
  isKeepAlive.value = [props.mainComponentName]
}
// 是否开启动画
const isAnimation = ref(false)
const onEnter = () => {
  isAnimation.value = true
}
const onLeave = () => {
  isAnimation.value = false
}
</script>
<style lang="scss" scoped>
// push页面时：新页面的进入动画
.push-enter-active {
  animation-name: push-in;
  animation-duration: 0.4s;
}
// push页面时：老页面的退出动画
.push-leave-active {
  animation-name: push-out;
  animation-duration: 0.4s;
}
// push页面时：新页面的进入动画
@keyframes push-in {
  0% {
    transform: translate(100%, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}
// push页面时：老页面的退出动画
@keyframes push-out {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-50%, 0);
  }
}

// 后退页面时：即将展示的页面动画
.back-enter-active {
  animation-name: back-in;
  animation-duration: 0.4s;
}
// 后退页面时：后退的页面执行的动画
.back-leave-active {
  animation-name: back-out;
  animation-duration: 0.4s;
}
// 后退页面时：即将展示的页面动画
@keyframes back-in {
  0% {
    width: 100%;
    transform: translate(-100%, 0);
  }
  100% {
    width: 100%;
    transform: translate(0, 0);
  }
}
// 后退页面时：后退的页面执行的动画
@keyframes back-out {
  0% {
    width: 100%;
    transform: translate(0, 0);
  }
  100% {
    width: 100%;
    transform: translate(50%, 0);
  }
}
</style>
